package pogvue.datamodel;

import pogvue.io.*;
import java.util.*;
import java.io.*;

public class KmerFrequency {
    Hashtable conserved_kmers;
    Hashtable nonconserved_kmers;

    int max_cons_count = -1;
    int max_noncons_count = -1;

    int conserved_tot = 0;
    int nonconserved_tot = 0;

    SequenceI seq;
    Vector    feat;

    int    kmer_size;
    int    kmer_count = -1;

    public KmerFrequency(int kmer_size,SequenceI seq, Vector feat) {
	this.kmer_size = kmer_size;
	this.seq       = seq;
	this.feat      = feat;

	getKmerCount();
    }

    public int getKmerCount() {
	if (kmer_count == -1) {
	    kmer_count = (int)(Math.pow(4,1.0*kmer_size));
	}
	return kmer_count;
    }

    public int getKmerSize() {
	return kmer_size;
    }

    public void index() {
	
	conserved_kmers    = KmerFrequency.index_kmers(seq,feat,kmer_size);
	System.out.println("Indexing here");

	nonconserved_kmers = KmerFrequency.index_nonfeat_kmers(seq,feat,kmer_size);
    }

    public int getMaxConsCount() {

	if (max_cons_count == -1) {
	    Enumeration en = conserved_kmers.keys();
	    
	    while (en.hasMoreElements()) {
		KmerIndex tmp = (KmerIndex)conserved_kmers.get(en.nextElement());
		
		if (tmp.getCount() > max_cons_count) {
		    max_cons_count = tmp.getCount();
		}
	    }
	}
	return max_cons_count;
	   
    }
    public int getMaxNonConsCount() {

	if (max_noncons_count == -1) {
	    Enumeration en = nonconserved_kmers.keys();
	    
	    while (en.hasMoreElements()) {
		KmerIndex tmp = (KmerIndex)nonconserved_kmers.get(en.nextElement());
		
		if (tmp.getCount() > max_noncons_count) {
		    max_noncons_count = tmp.getCount();
		}
	    }
	}
	return max_noncons_count;
	   
    }
    public int getRelativeCount(String kmer) {
	if (conserved_kmers.containsKey(kmer) &&
	    nonconserved_kmers.containsKey(kmer)) {

	    int conscount    = kmer_count * ((KmerIndex)conserved_kmers.get(kmer)).getCount()/getConservedTotal();
	    int nonconscount = kmer_count * ((KmerIndex)nonconserved_kmers.get(kmer)).getCount()/getNonConservedTotal();

	    if (nonconscount > 0) {
		return (int)(100*conscount/nonconscount);
	    } else {
		return 0;
	    }
	} else {
	    return 0;
	}
    }
    public int getConservedCount(String kmer) {
	if (conserved_kmers.containsKey(kmer)) {
	    return ((KmerIndex)conserved_kmers.get(kmer)).getCount();
	} else {
	    return 0;
	}

    }
    public int getNonConservedCount(String kmer) {
	if (nonconserved_kmers.containsKey(kmer)) {
	    return ((KmerIndex)nonconserved_kmers.get(kmer)).getCount();
	} else {
	    return 0;
	}

    }

    public Hashtable getConservedKmers() {
	return conserved_kmers;
    }
    public Hashtable getNonConservedKmers() {
	return nonconserved_kmers;
    }

    public int getConservedTotal() {
	
	if (conserved_tot == 0) {
	    
	    Enumeration en = conserved_kmers.keys();
	    
	    while (en.hasMoreElements()) {
		conserved_tot += ((KmerIndex)conserved_kmers.get(en.nextElement())).getCount();
	    }
	}
	return conserved_tot;
    }
    public int getNonConservedTotal() {
	if (nonconserved_tot == 0) {
	    Enumeration en = nonconserved_kmers.keys();
	    
	    while (en.hasMoreElements()) {
		nonconserved_tot += ((KmerIndex)nonconserved_kmers.get(en.nextElement())).getCount();
	    }
	}
	return nonconserved_tot;
    }
    public static Hashtable index_kmers(SequenceI seq,Vector feat,int kmer) {

	Hashtable feat_kmers    = new Hashtable();

	for (int j = 0; j < feat.size(); j++) {
	    SequenceFeature sf = (SequenceFeature)feat.elementAt(j);
	    
	    int start = sf.getStart() + kmer/2;
	    int end   = sf.getEnd() - kmer/2;

	    if (start < 0) {
		start = 0;
	    }

	    if (end > seq.getLength()-kmer) {
		end = seq.getLength()-kmer;
	    }
	    for (int i = start; i <= end; i++) {
		String tmp = seq.getSequence().substring(i-1,i+kmer-1).toUpperCase();
		
		if (!feat_kmers.containsKey(tmp)) {
		    KmerIndex index = new KmerIndex(tmp);
		    feat_kmers.put(tmp,index);
		}
		KmerIndex index = (KmerIndex)feat_kmers.get(tmp);

		index.addKmer(seq.getName(),i);
		
	    }
	}

	return feat_kmers;
    }

    public static Hashtable index_nonfeat_kmers(SequenceI seq,Vector feat,int kmer) {

	Hashtable nonfeat_kmers = new Hashtable();

	for (int i = kmer/2; i < seq.getLength()-kmer/2; i++) {
	    int start =  i -  kmer/2;
	    int end   =  i +  kmer/2;
	    
	    String tmp = seq.getSequence().substring(start,end).toUpperCase();
		
	    int overlap = 0;

	    for (int j = 0; j < feat.size(); j++) {

		SequenceFeature sf = (SequenceFeature)feat.elementAt(j);

		if (!(sf.getStart() > end ||
		      sf.getEnd()   < start)) {
		    overlap = 1;
		    j = feat.size();
		}
	    }
	    if (overlap == 0) {
		if (!nonfeat_kmers.containsKey(tmp)) {
		    KmerIndex index = new KmerIndex(tmp);
		    nonfeat_kmers.put(tmp,index);
		}
		KmerIndex index = (KmerIndex)nonfeat_kmers.get(tmp);
		
		index.addKmer(seq.getName(),i);
	    }
	
	}
	return nonfeat_kmers;
    }

}

